function $_(obj)
{
	return document.getElementById(obj);
}

function debug(s)
{
	if (!_debug) return;
	if (console)
	{
		console.log(s);
	}
	else
	{
		alert(s);
	}
}

function download(f)
{
var bggg = document.createElement('div');
var page = get_page_size();
$(bggg).css(
	{
		height: page.height,
		width: page.width,
		zIndex: '999',
		display:'none',
		position:'absolute',
		top:'0px',
		left:'0px',
		padding:'0px',
		margin:'0px'
	})
	.fadeTo(1,0,function(){ this.style.display = ''; })
	.attr('preview','yes')
	.bind('click',close_preview);
	//.html('<br /><br /><br /><div id="dl_msg" />');
	
$(document.body).append(bggg);

$(bggg).css('background-color','#000000').fadeTo(100,0.6);

var page = get_page_size();
var dl_msg = document.createElement('div');
$(dl_msg).css({
	'height':'30px',
	width: page.width,
	'display':'none',
	'position':'absolute',
	'top':'100px',
	//'left':'0px',
	'padding':'0px',
	'margin':'0px',
	'zIndex':'99999',
	'font-size':'200%',
	'text-align':'center'
})
	.fadeTo(1,0,function(){ this.style.display = ''; })
	.attr('preview','yes')
	.bind('click',close_preview)
	//.html("{DOWNLOAD_NEED_MUCH_TIME}");
	.append("{DOWNLOAD_NEED_MUCH_TIME}");
$(document.body).append(dl_msg);
//$(dl_msg).css('z-index','99999').fadeTo('fast',1);
$(dl_msg).css({'color':'#fff','background-color':'#000000'}).fadeTo(100,1);
	
document.oncontextmenu = function() { return false; };
$(document).unbind('contextmenu');

	var arr = $('.file_on_select');
	if (arr.length == 1 && !f)
	{
		var name = arr.attr('display_name');
		name = encodeURIComponent(name);
		var url = './download/'+arr.attr('path')+'/'+name;
		if (arr.attr('folder') == 'yes') url += '.zip';
		inwin.window.location = url;
	}
	else if (arr.length == 0 && !f)
	{
		var p = decode_path(window.path.replace(root,''));
		if (p.substring(p.length-1,p.length) == '/') p = p.substring(0,p.length-1);
		var arr = p.split('/');
	
		p = arr[arr.length-1];
		if (!p) p = '{customer.name}';
		var url = './download/'+window.path+'/'+p+'.zip';
		inwin.window.location = url;
	}
	else if (f)
	{
		var p = '{customer.name}';
		var url = './download/'+root+'/'+p+'.zip';
		inwin.window.location = url;
	}
}

function setcookie(name,value,t) 
{
	var cookiestr=name+"="+UrlEncode(value)+";";
	var expires = "";
	var d = new Date();
	var t2=(!t)?cookieexp:t*60*1000;
	d.setTime( d.getTime() + cookieexp);
	expires = "expires=" + d.toGMTString()+";";
	document.cookie = cookiestr+ expires;
}

function get_log()
{
	var f = $('[file=yes].file_on_select');
	var d = $('[folder=yes].file_on_select');
	if (f.length == 1 && d.length ==0)
	{
		sendcomm("log","file",f.attr('path'),0,0,0);
	}
	else if (d.length == 1 && f.length ==0)
	{
		sendcomm('log','file',d.attr('path'),0,0,0);
	}
	else if (d.length ==0 && f.length == 0 && path)
	{
		sendcomm('log','file',path,0,0,0);
	}
}

function show_log(log,path)
{
	$('#log_list_tbody').html('');
	var body = $_('log_list_tbody');
	for(i=0;i<log.length;i++)
	{
		var tr = body.insertRow(-1);
		tr.insertCell(-1).innerHTML = log[i].file;
		tr.insertCell(-1).innerHTML = log[i].action_str;
		tr.insertCell(-1).innerHTML = log[i].user;
		tr.insertCell(-1).innerHTML = log[i].time;
		tr.insertCell(-1).innerHTML = log[i].other;
	}
	$('#log').each(function(){ center(this,20); }).fadeIn(300);
	$('#log_path_div').html(path);
}

function get_delete_log(keyword)
{
	sendcomm('delete_log','keyword',keyword,0,0,0);
}

function show_delete_log(log,path)
{
	$('#delete_log_list_tbody').html('');
	var body = $_('delete_log_list_tbody');
	var r_from = 0;
	for(i=0;i<log.length;i++)
	{
		var tr = body.insertRow(-1);
		tr.insertCell(-1).innerHTML = log[i].file;
		tr.insertCell(-1).innerHTML = log[i].action_str;
		tr.insertCell(-1).innerHTML = log[i].user;
		tr.insertCell(-1).innerHTML = log[i].time;
		//tr.insertCell(-1).innerHTML = log[i].other;
		//tr.insertCell(-1).innerHTML = log[i].r;
		//tr.insertCell(-1).innerHTML = "<form name='delete_log_form' id='delfile' style='margin:0px;padding: 0;' action='#' onsubmit='revert_candidate_log_do(this);return false;'>"
		tr.insertCell(-1).innerHTML = "<form name='delete_log_form' id='delfile' style='margin:0px;padding: 0;' action='#' onsubmit='revert_candidate_do(this);return false;'>"
									+ "<input type='hidden' name='encodedfilepath' value='"+log[i].encodedfile+"'>"
									+ "<input type='hidden' name='filename' value='"+log[i].file+"'>"
									+ "<input type='hidden' name='revision' value='"+log[i].r+"'>"
									+ "<input type='hidden' name='time' value='"+log[i].time+"'>"
									//+ "<input type='submit' value='{GO_REVERT_CANDIDATE_LOG}'></form>";
									+ "<input type='submit' value='{GO_REVERT_CANDIDATE}'></form>";

	}
	$('#delete_log').each(function(){ center(this,20); }).fadeIn(300);
	$('#delete_log_path_div').html(path);
}

function show_revert_candidate_log(log,path)
{
	$('#revert_candidate_log_list_tbody').html('');
	var body = $_('revert_candidate_log_list_tbody');
	var r_from = 0;
	for(i=0;i<log.length;i++)
	{
		var tr = body.insertRow(-1);
		tr.insertCell(-1).innerHTML = log[i].file;
		tr.insertCell(-1).innerHTML = log[i].action_str;
		tr.insertCell(-1).innerHTML = log[i].user;
		tr.insertCell(-1).innerHTML = log[i].time;
		tr.insertCell(-1).innerHTML = log[i].other;
		//tr.insertCell(-1).innerHTML = log[i].r;
		//if (log[i].action=='upload'||log[i].action=='update') {
		if (log[i].action!='delete') {
			tr.insertCell(-1).innerHTML = "<form name='revert_candidate_log_form' id='candidate' style='margin:0px;padding: 0;' action='#' onsubmit='revert_candidate_do(this);return false;'>"
									+ "<input type='hidden' name='encodedfilepath' value='"+log[i].encodedfile+"'>"
										+ "<input type='hidden' name='filename' value='"+log[i].file+"'>"
										+ "<input type='hidden' name='revision' value='"+log[i].r+"'>"
										+ "<input type='hidden' name='time' value='"+log[i].time+"'>"
										+ "<input type='submit' value='{GO_REVERT_CANDIDATE}'></form>";
		} else {
			tr.insertCell(-1).innerHTML = '';
		}


	}
	$('#revert_candidate_log').each(function(){ center(this,20); }).fadeIn(300);
	$('#revert_candidate_log_path_div').html(path);
}

function revert_candidate_log_do(f)
{
	sendcomm('revert_candidate_log',['filename','revision'],[f.filename.value,f.revision.value],0,0,0);
}

function revert_candidate_do(f)
{
	sendcomm('revert_candidate',['encodedfilepath','filename','revision','time','path'],[f.encodedfilepath.value,f.filename.value,f.revision.value,f.time.value,path],0,0,0);
}

function lock_and_download()
{
	var arr = $('.file_on_select');
	if (arr.length == 1 && arr.attr('file') == 'yes')
	{
		var url = './lockanddown/'+arr.attr('path')+'/'+arr.attr('display_name');
		inwin.window.location = url;
		setTimeout("do_refresh();",2000);
	}
}

function check_upload_file(f)
{
	if (f.value)
	{
		var name = f.value;
		var arr = name.split('/');
		if (name.indexOf('\\') != -1)
		{
			arr = name.split('\\');
		}
		name = arr[arr.length-1];
		$('[file]').each(function()
		{
			if ($(this).attr('display_name') == name)
			{
					if (!confirm('{DO_YOU_WANT_UPDATE}'))
					{
						clearupfile();
					}
					else
					{
						waitme();
						upform.submit();
					}
			}
		});
		
	}
}

function checkfile()
{
	var i,files='',dirs='';
	var dirn=0;
	var filen=0;
	var dir = jQuery('[folder=yes].file_on_select');
	dirn = dir.length;
	var file = $('[file=yes].file_on_select');
	filen = file.length;
	
	dir.each(function ()
	{
		dirs += $(this).attr('path')+"|";
	});
	
	file.each(function()
	{
		files+= $(this).attr('path')+"|";
	});
	r=new Array();
	r["dn"]=dirn;
	r["fn"]=filen;
	r["sdir"]=dirs;
	r["sfile"]=files;
	return r;
}

function open_selected_file()
{
	var arr = checkfile();
	if (arr["fn"] + arr["dn"] == 0)
	{
		notice("{NO_SELECT}");
	}
	if (arr['dn'] == 1)
	{
		opendir($('.file_on_select').attr('path'));
	}
	else if (arr['fn'] == 1)
	{
		$('.file_on_select').trigger('dblclick');
	}
}


function filecopy(action)
{
	var i=0,n=0;
	var filestr='',dirstr='';
	var act=(action == "copy")?"{COPY}":"{CUT}";
	if (action == 'cut')
	{
		$('.list_div').fadeTo(100,1);
		$('.file_on_select').find('div').fadeTo(100,0.5);
	}
	else
	{
		action = 'copy';
	}
	var arr=checkfile();
	if (arr["dn"]+arr["fn"] ==0 ) notice('{NO_SELECT}');
	window.copy_action1 = action;
	window.copy_sdir = arr["sdir"];
	window.copy_sfile = arr["sfile"];
	window.copy_from = path;
}

function filepaste()
{
	if (window.copy_action1)
	{
//alert("window.copy_action1::"+window.copy_action1+"\r\n"
//+"window.copy_sdir::"+window.copy_sdir+"\r\n"
//+"window.copy_sfile::"+window.copy_sfile+"\r\n"
//+"window.copy_from::"+window.copy_from+"\r\n");
		if (window.copy_action1 ==  'cut' && window.copy_from == path)
		{
			alert('{CAN_NOT_MOVE_HERE}');
			return;
		}
		waitme();
		//sendcomm("paste",['sdir','sfile','path','action1'],[copy_sdir,copy_sfile,path,copy_action1],0,0,0);
		sendcomm("paste",['sdir','sfile','path','action1'],[window.copy_sdir,window.copy_sfile,path,window.copy_action1],0,0,0);
	}
}


function filedel()
{
	var i,arr=checkfile(),dn=0,alt;
	if (arr['fn']+arr['dn']==0)
	{
		notice("{NO_SELECT}");
		return;
	}
	if ($('.file_on_select').length == 1 && $(".file_on_select").attr('lockedby'))
	{
		
	}
	else
	{
		if (!confirm('{CONFIRM_DEL}')) return;
	}
	//if (arr['dn'] && !confirm('{CONFIRM_DEL_FOLDER}')) return;
	sendcomm("delete",Array("path","sdir","sfile"),Array(path,arr['sdir'],arr['sfile']));
}

function upload()
{
	var o = $('#upload');
	if (o.attr('show'))
	{
		o.removeAttr('show').fadeOut(500);
	}
	else
	{
		center(o);
		o.attr('show','yes').fadeIn(500);
	}
}

function waitme()
{
	$('#loading').html('{LOADING}').animate({ top:0 });
	window.status = "{LOADING}";
	return true;
}

function waitmeoff()  
{
	$('#loading').animate({ top:-50 });
	window.status='OK';
	return true;
}

function filerename()
{
	if (window.in_preview) return;
	var obj = $('.file_on_select');
	if (obj.length == 1)
	{
		var offset = obj.offset();
		$('#rename_div').css(
		{
			left:offset.left+30,
			top:offset.top,
			width:500,
			height:obj.height()
		});
		$('#rename_form').find('[name=name]')
		.val(obj.attr('display_name'))
		.attr('old_name',obj.attr('path'))
		.attr('old_display_name',obj.attr('display_name'))
		.bind('blur',rename_do)
		.css('width',obj.find('.list_file_name').width()+100)
		$('#rename_div').fadeIn(300,function(){ window.renaming=false; });
		setTimeout("try{ $_('rename_form').name.focus();$_('rename_form').name.select(); } catch(e){ }",200);
	}
}

function rename_do()
{
	var name = $('#rename_form').find('[name=name]');
	if (name.attr('old_display_name') != name.val() && name.val() != '')
	{
		var filename = name.attr('old_name');
		var new_name = name.val();
		if (!checkfilename(new_name)) return;
		if (window.renaming) return;
		window.renaming = true;
		sendcomm("rename",["new_name","filename"],[new_name,filename],0,0,1);
	}
	$('#rename_div').fadeOut(300,function(){  $('#rename_form').find('[name=name]').val('');window.renaming = false; });
	return false;
}

function allcheck()
{
	$('#list_tbody tr').addClass('file_on_select');
}

function inverse()
{
	$('tr[list_item=yes]').toggleClass('file_on_select');
}

function password()
{
	var html = "<form name='password_form' id='password_form' style='margin:4px' action='#' onsubmit='password_do(this);return false;'>";
	html+= "{CHANGE_PASSWORD}<br /><br /><table border=0><tr><td>{PASSWORD}</td><td><input type=password size=20 name='password' value='' /></td></tr>";
	html+= "<tr><td>{RE_TYPE}</td><td><input type=password name='password2' value='' /></td></tr></table><br />";
	html += "<input type=submit class=bt value='{GO_PASSWORD}' /> <input type=button class=bt value='{CANCEL}' onclick='close_notice(1)' /></form>";
	window.movenotice = 0;
	notice(html,30,mouse_x,mouse_y,1);
}

function open_search()
{
	$('.functiondiv').fadeOut(100);
	var html = "<form name='search_form' id='search_form' style='margin:4px' action='#' onsubmit='search(this);return false;'>";
	html+= "{SEARCH_TITLE}<br /><br /><input type='text' size='20' name='keyword' value='' /><br /><br />";
	html += "<input type='submit' class=bt value='{GO_SEARCH}' /> <input type=button class=bt value='{CANCEL}' onclick='close_notice(1)' /></form>";
	window.movenotice = 0;
	notice(html,30,mouse_x,mouse_y,1);
	setTimeout("try{ $_('search_form').keyword.focus();} catch(e){ }",200);
}
window.searching = false;
function search(f)
{
	var keyword = f.keyword.value;
	if (keyword)
	{
		window.search_keyword = keyword;
		window.searching = true;
		if (!window.path || window.path == 'search')
			var sp = window.root;
		else 
			var sp = window.path;
		window.search_path = sp;
		reloaddata(sp,0,0,0,keyword);
		close_notice(1);
	}
}

function open_delete_search()
{
	var html = "<form name='search_form' id='search_form' style='margin:4px' action='#' onsubmit='delete_search(this);return false;'>";
	html+= "{DELETE_SEARCH_TITLE}<br /><br /><input type='text' size='20' name='keyword' value='' /><br /><br />";
	html += "<input type='submit' class=bt value='{GO_DELETE_SEARCH}' /> <input type=button class=bt value='{CANCEL}' onclick='close_notice(1)' /></form>";
	window.movenotice = 0;
	notice(html,30,mouse_x,mouse_y,1);
	setTimeout("try{ $_('search_form').keyword.focus();} catch(e){ }",200);
}
window.searching = false;
function delete_search(f)
{
	var keyword = f.keyword.value;
	if (keyword)
	{
		get_delete_log(keyword);
		close_notice(1);
	}
}


function password_do(f)
{
	if (f.password.value != f.password2.value)
	{
		alert('{PASSWORD_NOT_THE_SAME}');
		return;
	}
	sendcomm('password','password',f.password.value);
}

function newfile(f)
{
	debug("newfile");
	if (!f)
	{
		html = "<form name='new_file_form' id='new_file_form' style='margin:4px' action='#' onsubmit='new_file_do(this);return false;'>";
		html+= "{NEW_FILE_TITLE}<br /><input type=text size=20 name='name' value='' />&nbsp;<input type=submit class=bt value='{GO_NEW_FILE}' /> <input type=button class=bt value='{CANCEL}' onclick='close_notice(1)' /></form>";
		window.movenotice = 0;
		notice(html,30,mouse_x,mouse_y,1);
		setTimeout("try{ $_('new_file_form').name.focus();} catch(e){ }",200);
	}
	else
	{
		html = "<form name='new_folder_form' id='new_folder_form' style='margin:4px' action='#' onsubmit='new_folder_do(this);return false;'>";
		html+= "{NEW_FOLDER_TITLE}<br /><input type=text size=20 name='name' value='' />&nbsp;<input type=submit class=bt value='{GO_NEW_FOLDER}' /> <input type=button class=bt value='{CANCEL}' onclick='close_notice(1)' /></form>";
		window.movenotice = 0;
		notice(html,30,mouse_x,mouse_y,1);
		setTimeout("try { $_('new_folder_form').name.focus(); } catch(e){ }",200);
	}
}

function new_folder_do(f)
{
	var name = f.name.value;
	if (!name)
	{
		return false;
	}
	else
	{
		if (!checkfilename(name)) return;
		sendcomm('newdir',['name','path'],[name,path]);
		close_notice();
	}
}

function revert(d)
{
	
	if (d == 7)
		d = "1 {R_WEEK}<input type='hidden' id='revert_days_input' value='7' />";
	else if (d>1)
		d = d+" {R_DAYS}<input type='hidden' id='revert_days_input' value='"+d+"' />";
	else if (d == 1)
		d = "1 {R_DAY}<input type='hidden' id='revert_days_input' value='1' />";
	else if (d == -1)
	{
		revert_do(-1);
		return;
	}
	else if (d == 'latest')
	{
		revert_latest(-1);
		return;
	}
	else
	{
		revert_to();
		return;
	}
	$('#revert').each(function(){ center(this); }).fadeIn(300);
	$('#revert_days').html(d);
}

function revert_to()
{
	dd = new Date();
	year = dd.getYear();
	if (year < 2000) year += 1900;
	month = dd.getMonth() + 1;
	day = dd.getDate();

	$('#revert_to_year').val(year);
	$('#revert_to_month').val(month);
	$('#revert_to_day').val(day);
	$('#revert_to_hour').val('00');
	$('#revert_to_minute').val('00');
	$('#revert_to_second').val('00');
	$('#revert_to').each(function(){ center(this); }).fadeIn(300);
}

function revert_to_do()
{
	var i,arr=checkfile(),dn=0,alt;
	if (arr['fn']+arr['dn']==0)
	{
		notice("{NO_SELECT}");
		return;
	}
	var names = [];
	var vals = [];
	$('input[id^=revert_to_]').each(function()
	{
		names.push(this.id.replace('revert_to_',''));
		vals.push(parseInt(this.value, 10));
	});
	names.push('path');
	vals.push(path);
	names.push('sfile');
	vals.push(arr['sfile']);
	names.push('sdir');
	vals.push(arr['sdir']);
	names.push('action1');
	vals.push('revert_to');
	
	sendcomm("revert",names,vals);
}

function revert_do(d)
{
	var i,arr=checkfile(),dn=0,alt;
	if (arr['fn']+arr['dn']==0)
	{
		notice("{NO_SELECT}");
		return;
	}
	if (!d) d= $('#revert_days_input').val();
	sendcomm("revert",Array("path","sdir","sfile","days"),Array(path,arr['sdir'],arr['sfile'],d));
}

function revert_latest()
{
	var i,arr=checkfile(),dn=0,alt;
	if (arr['fn']+arr['dn']==0)
	{
		notice("{NO_SELECT}");
		return;
	}
	//if (!d) d= $('#revert_days_input').val();
	sendcomm("revert",Array("path","sdir","sfile","action1"),Array(path,arr['sdir'],arr['sfile'],'revert_latest'));
}

function close_revert()
{
	$('#revert').fadeOut(500);
}

function center(o,upper)
{
	if (!upper) upper = 50;
	$(o).animate( 
	{
		'left' : ($(window).width() - $(o).width() ) / 2 ,
		'top' : ( ($(window).height() - $(o).height() ) / 2) -upper
	},300);
}

function new_file_do(f)
{
	var name = f.name.value;
	if (!name)
	{
		return false;
	}
	else
	{
		if (!checkfilename(name)) return;
		sendcomm('newfile',['name','path'],[name,path]);
		close_notice();
	}
}

function sendcomm(act,vars,vals,func,re,al,method)
{
//alert("act::"+act+"\r\nvars::"+vars+"\r\nvals::"+vals);
	var path1=window.path;
	waitme();
	debug("comm ");
	var data = { action: act };
	if (typeof(vars)=="object")
	{
		if (vars.length!=vals.length) return false;
		var i=0;
		for(i=0;i<vars.length;i++) data[vars[i]] = vals[i];	
	}
	else data[vars] = vals;
	
	var success = (func)?func:function(re)
	{
		debug("ajax response :"+re);
		var res=checkdata(re);
		if (res==-1)
			notice("Error:\n"+pickdata(re));
		else if (res==1)
		{
			if (!al) notice(pickdata(re));
			if (!re) reloaddata(path1);
		}
		else if (res !=2)
			notice(re);
		waitmeoff();
	}

	var error = function()
	{
		alert(act+' error!');
		waitmeoff();
	}
	
	$.ajax(
	{
		'data':data,
		'success':success,
		'error':error,
		'method':'POST'
	});
}


function upindex()
{
	var path=window.path;
	var root=window.root;
	if (path.indexOf(root) !=0) path = root;
	if (path == root)
	{
		notice("{NO_UP}!",1);
		return;
	}
	var arr = path.split("/");
	var i;
	path = "";
	for(i=0;i<arr.length-2;i++) path+=arr[i]+"/";
	window.path = path;
	opendir(path);
}

function resetdata(s,vname)
{
	if (!s) return;
	var arr=s.split("|");
	for(i=0;i<arr.length;i++)
	{
		if (arr[i]=="") continue;
		eval(vname+"['"+arr[i]+"']=true;");
	}
}

function checkdata(s)
{
	if (s.indexOf("+OK=")!=-1) return 1;
	else if (s.indexOf("+Error=")!=-1) return -1;
	else if (s.indexOf("+Eval=")!=-1)
	{
		debug("Eval:\n"+pickdata(s));
		eval(pickdata(s));
		return 2;
	}
	else return 0;
}

function pickdata(s)
{
	if (s.length<=0) return false;
	var arr=s.split("==?");
	arr=arr[1].split("?==");
	return arr[0];
}

function opendir(path)
{
	window.searching = false;
	debug("opendir :"+path);
	if (!path) path = root;
	if (!data[path])
	{
		reloaddata(path,1,0);
		return;
	}
	else
	{
		window.path=path;
		display();
	}
}

function do_refresh()
{
	if (window.searching)
	{
		$.post('index.php?p=ajax&action=noop',{ },function(){ });
	}
	else
	{
		reloaddata(null,null,null,true);
	}
}

function reloaddata(p,r,tree,do_st,keyword)
{
	if (!p) p = window.path;
	if (p == 'search')
	{
		keyword = window.search_keyword;
		p = window.search_path;
	}
	if (p.charAt(p.length-1) != "/") p+="/";
	debug("reloaddata :"+p);
	do_st = (do_st)?'yes':'';
	$.ajax(
	{
		data:
		{
			action:keyword?'search':'list',
			path:p,
			keyword:keyword?keyword:''
		},
		success:function(re)
		{
			debug('reloaddata response:'+re);
			var res=checkdata(re);
			if (res == 1)
			{
				if (!window.searching) data[p] = pickdata(re);
				else	data['search'] = pickdata(re);
				debug("refreshed data from "+p+" and here is "+path);
				if (p == path || window.searching) display(p,tree);
				else if (r)
				{
					if (!tree) window.path = p;
					display(p,tree);
				}
			}
			waitmeoff();
		},
		error:function()
		{
			debug("Ajax error: path="+p);
		}
	});
	waitme();
}

function display(p,tree)
{
	if (tree) var path = p;
	else path = window.path;
	if (window.searching) path = 'search';

	debug("display data:"+data[path]);
	if (typeof(data[path])=="string" && data[path]!="")
	{
		debug("data["+path+"]=string");
		var d=data[path];
		try
		{
			eval('var arr = '+d+';');
		}catch(e){ alert('JSON Syntax Error!'); return; }
		data[path] = arr;

		if (!tree)
		{
			window.list = arr;
		}
		else
		{
			mdir = get_dirs(arr);
		}
	}
	else if (typeof(data[path]) == "object")
	{	
		debug("data["+path+"]=array");
		if (!tree)
		{
			window.list = data[path];
		}
		else
		{
			mdir = get_dirs(data[path]);
		}
	}
	if (!tree) 
	{
		window.path=path;
		window.vdis='inline';
	}
	if (!tree) refresh();
	else
	{
		open_tree(p,mdir,1);
	}
}


function get_dirs(arr)
{
	var mdir = [];
	for(var i=0;i<arr.length;i++)
	{
		if (arr[i].type == 'folder')
		{
			mdir.push(arr[i]);
		}
	}
	return mdir;
}

function get_dir_string(dir)
{
	var re = '';
	for(var i=0;i<dir.length;i++)
	{
		re+= dir[i].name
	}
	return re;
}

function open_tree(path,dir)
{
	if (typeof data[path] != "object")
	{
		//alert("reload:"+path);
		reloaddata(path,1,1);
		return;
	}
	var dir = dir?dir:get_dirs(data[path]);
	var html='';
	var i=0,f='';
	var folder_id = "folder_"+path_to_id[path];
	//alert(folder_id);
	
	var img = $_(folder_id.replace('folder_','folder_image1_'));
	if (img) img.src = window.image_path+'/minus.png';
	var img = $_(folder_id.replace('folder_','folder_image2_'));
	if (img) img.src = window.image_path+'/openfolder.png';
	//alert(dir.length +" "+ $_(folder_id).childNodes.length);
	//if (tree_data[path]) alert(tree_data[path].length);
	if (!tree_data[path] || tree_data[path] != get_dir_string(dir))
	{
		//alert(path+' = '+window.tree_data[path])
		window.tree_data[path] = get_dir_string(dir);
		if (dir.length == 0)
		{
			var fobj = $_(folder_id);
			if (!fobj) return;
			$('#'+folder_id.replace('folder_','folder_image1_')).fadeTo(100,0.001);
			while(fobj.childNodes.length > 0) fobj.removeChild(fobj.firstChild);
			setTimeout("$_('"+folder_id+"'.replace('folder_','folder_image2_')).src = '"+window.image_path+"/folder.png';",1000);
		}
		else
		{
			var o = $_(folder_id);
			if (!o) return;
			o.style.display = 'none';
			o.innerHTML = '';
			$('#'+folder_id.replace('folder_','folder_image1_')).fadeTo(100,1);

			for (i=0;i<dir.length;i++)
			{

				var table = document.createElement('table');
				$(table).attr({ cellpadding:0,cellspacing:1,border:0 });
				var tr = table.insertRow(-1);
				$(tr)
				.attr('name',dir[i].name)
				.attr('display_name',dir[i].display_name)
				.attr('path',dir[i].path)
				.attr('folder','yes');
				
				$(tr.insertCell(-1)).css('width','13px').html("<a href='javascript:;' onclick='expand_tree(this)' title='"+dir[i].path+"'><img src='"+window.image_path+"/plus.png' border=0 id='folder_image1_"+id_to_path.length+"' /></a>");
				$(tr.insertCell(-1)).html("<a href=\"javascript:opendir('"+dir[i].path+"');\"><img src='"+window.image_path+"/folder.png' id='folder_image2_"+id_to_path.length+"' border=0 /></a>");
				$(tr.insertCell(-1)).html("<span class='treeview name' id='tree_name_"+id_to_path.length+"'><nobr><a href=\"javascript:opendir('"+dir[i].path+"');\">"+dir[i].display_name+"</a></nobr></span>");
				
				var div2 = document.createElement('div');
				$(div2).attr('id','folder_'+id_to_path.length).addClass('treeview').addClass('list_wraper').css('display','none');
				
				var div = document.createElement('div');
				$(div)
				.addClass('treeview')
				.addClass('list_item')
				.append(table)
				.append(div2);
				
				o.appendChild(div);
				
				path_to_id[dir[i].path] = id_to_path.length;
				path_to_name[dir[i].path] = dir[i].display_name;
				id_to_path[id_to_path.length] = dir[i].path;
			}
			
			tree_downloaded[path] = true;
			$(o).slideDown(500);
		}
	}
	else
	{
		$('#'+folder_id).slideDown(500);
	}
}

function find_parent_node(o,s)
{
	while(o.tagName.toString().toLowerCase()!= s.toLowerCase())
	{
		if (o.parentNode.tagName)
			o = o.parentNode;
		else return o;
	}
	return o;
}

function find_child_node(o,s)
{
	while(o.tagName.toString().toLowerCase()!= s.toLowerCase())
	{
		o = o.firstChild;
	}
	return o;
}

function expand_tree(o)
{
	if (typeof o == "string")
	{
		expand_tree_by_folder_id(o);
		return;
	}
	

	if (find_parent_node(o,'table').nextSibling.style.display == 'none' )
	{
	//alert("expading tree "+o.title);
	//if (!tree_downloaded[o.title])
	//{
		//alert(o.title);
		open_tree(o.title);
		return;
	//}
		//o.firstChild.src = window.image_path+"/minus.png";
		//o.parentNode.nextSibling.firstChild.src = window.image_path+"/openfolder.png";
		//find_parent_node(o,'table').nextSibling.style.display = '';
	}
	else
	{
		//alert(o.firstChild.tagName + ' '+image_path+'/plus.png');
		$(o.firstChild).attr('src',window.image_path+"/plus.png");
		
		o.parentNode.nextSibling.firstChild.src = window.image_path+"/folder.png";
		$(find_parent_node(o,'table').nextSibling).slideUp(500);
	}
}


function expand_tree_by_folder_id(fid)
{
	//alert("expanding "+fid);
	var f = $_(fid);
	if (f.style.display == 'none')
	{
		f.style.display = 'block';
		find_child_node(f,'img').src = window.image_path+"/minus.png";
		find_child_node(f,'td').nextSibling.firstChild.src = window.image_path+"/openfolder.png";
	}
	else
	{
		f.style.display = 'none';
		find_child_node(f,'img').src = window.image_path+"/plus.png";
		find_child_node(f,'td').nextSibling.firstChild.src = window.image_path+"/folder.png";
	}
}

function get_base_name(s)
{
	var arr = s.split('/');
	if (s == root) return '{ROOT}';
	return ( arr[arr.length-2])?  arr[arr.length-2]:'';
}

function if_rename(event,o)
{
	o = find_parent_node(o,'table');
	o = find_parent_node(o,'tr');
	if ($(o).hasClass('file_on_select') && $('.file_on_select').length == 1)
	{
		window.rename_timer = setTimeout("filerename()",700);
	}
}

function get_list_string(list)
{
	var re = path+'||';
	for(i=0;i<list.length;i++)
	{
		if (list[i].type == 'folder')
			re += list[i].name+'|'+list[i].modified+'||';
		else
			re += list[i].name+'|'+list[i].locked+'|'+list[i].modified+'|'+list[i].bytes+'||';
	}
	return re;
}

function refresh()
{
	debug("refresh");
	// refresh tree view
	window.last_list_items_temp = '';
	if (!window.searching)
	{
		if ($('[hidewhensearch=yes]').attr('hidden') == 'yes')
		{
			$('[hidewhensearch=yes]').attr('hidden','no').css('cursor','pointer').each(function()
			{
				this.onclick = this.old_click?this.old_click:null;
			}).fadeTo(100,1);
		}
		open_tree(path);
	}
	else
	{
		$('[hidewhensearch=yes]').attr('hidden','yes').css('cursor','default').each(function()
		{
			this.old_click = this.onclick;
			this.onclick = null;
		}).fadeTo(100,0.2);
	}
	
	if (!window.searching && window.current_list_string == get_list_string(list)) return;
	$('#list_main_table').html(window.list_table_html);//.append(window.clean_list_table.cloneNode(1));
	
	var body = $_('list_tbody');
	//while(body.childNodes.length) body.removeChild(body.firstChild);
	body.innerHTML = '';

	for(var i=0;i<list.length;i++)
	{
		var tr = body.insertRow(-1);
		if (list[i].type == 'folder')
		{
			$(tr).attr(
				{
					'folder':'yes',
					'name':list[i].name,
					'display_name':list[i].display_name,
					'path':list[i].path,
					'list_item':'yes'
				})
			.bind('dblclick',function()
			{ 
				try{ clearTimeout(window.rename_timer); } catch(e) { }
				opendir($(this).attr('path')) 
			});
			
			var div = document.createElement('div');
			var name = list[i].display_name?list[i].display_name:list[i].name;
			$(div)
			.addClass('list_div')
			.css('background-image','url(public/images/icons/'+icon['folder']+')')
			.html('<span class="list_file_name" ><table cellspacing=0 cellpadding=0 border=0><tr style="background-color:transparent;"><td><span onclick="if_rename(event,this)">'+name+'</span></td></tr></table></span>')
			.css('cursor','normal');
			if (window.searching)
			{
				
				$(div)
				.attr('path',decode_path(list[i].path.replace(root,'')))
				.bind('mouseover',function()
				{
					notice($(this).attr('path'));
				}).bind('mouseout',function(){ $('#notice').css('display','none'); });
			}
			tr.insertCell(-1).appendChild(div);
			tr.insertCell(-1).innerHTML = ' ';
		}
		else
		{
			$(tr).attr(
				{
					'file':'yes',
					'name':list[i].name,
					'display_name':list[i].display_name,
					'path':list[i].path,
					'list_item':'yes'
				})
			.bind('dblclick',function()
			{ 
				try{ clearTimeout(window.rename_timer); } catch(e) { }
				//inwin.window.location = './download/'+$(this).attr('path')+'/'+encodeURIComponent($(this).attr('display_name')); 
				download();
			});
			
				
			
			var arr = list[i].display_name.split('.');
			var ext = arr[arr.length-1].toLowerCase();
			var icon_image =  (icon[ext])?icon[ext]:icon['default'];
			var div = document.createElement('div');
			var name = list[i].display_name?list[i].display_name:list[i].name;
			
			
			if (imgfiles.indexOf('|'+ext+'|') != -1)
			{
				$(tr).unbind('dblclick').bind('dblclick',image_preview);
			}
			
			$(div)
			.addClass('list_div')
			.css('background-image','url(public/images/icons/'+icon_image+')')
			.html('<span class="list_file_name"><table cellspacing=0 cellpadding=0 border=0><tr style="background-color:transparent;"><td><span onclick="if_rename(event,this)">'+name+'</span></td></tr></table></span>');
			if (window.searching)
			{
				$(div)
				.attr('path',decode_path(list[i].path.replace(root,'')))
				.bind('mouseover',function()
				{
					notice($(this).attr('path'));
				}).bind('mouseout',function(){ $('#notice').css('display','none'); });
			}
			tr.insertCell(-1).appendChild(div);
			
			
			var sizetd = tr.insertCell(-1);
			$(sizetd).html(list[i].size).attr('sort',list[i].bytes);
		}
		tr.insertCell(-1).innerHTML = list[i].ftype;
		tr.insertCell(-1).innerHTML = list[i].modified;	
		
		var listi_s = '';
		if (list[i].type == 'folder')
			listi_s = list[i].name+'|'+list[i].modified+'||';
		else
			listi_s += list[i].name+'|'+'|'+list[i].modified+'|'+list[i].bytes+'||';
		
		window.last_list_items_temp += '|'+listi_s+'|';
		if (window.path == window.last_path && window.last_list_items)
		{
			if (window.last_list_items.indexOf('|'+listi_s+'|') == -1)
				$(tr).addClass('file_on_select');
			else
				$(tr).removeClass('file_on_select');
		}
	}
	
	window.current_list_string = (!window.searching)?get_list_string(list):'searched';
	total();
}

function total()
{
	window.last_path = path;
	window.last_list_items = window.last_list_items_temp;
	$('#list_tbody tr')
		.bind('contextmenu',file_on_contextmenu)
		.bind('click',file_on_click)
		
	
	var fi = $_('file_count');
	var fo = $_('folder_count');
	if (!fi || !fo) return;
	fo.innerHTML = get_dirs(list).length;
	fi.innerHTML = list.length - fo.innerHTML;
	$_('upsavepath').value = window.path;
	
	//$('#list_table').tablesorter();

	init_drag_and_select();
	history_add(path);

	$('#current_path').html(dealpath(path));

	$('.tree_on_select').removeClass('tree_on_select');
	if (path == root)
	{
		$('#root_folder_name').addClass('tree_on_select');
	}
	else
	{
		$('#tree_name_'+path_to_id[path]).addClass('tree_on_select');
	}
}

function history_add(path)
{
	if (historyf && !historyf.prevent_add_history)
	{
		window.prevent_history_open = true;
		setTimeout('window.prevent_history_open = false',1000);
		historyf.location = 'history.html#path='+path;
	}
}

function file_on_contextmenu(event)
{
	if (!$(this).hasClass('file_on_select'))
	{
		$(this).trigger('click');
	}
}

function file_on_click(event)
{
	window.click_delay = true;
	setTimeout('window.click_delay = false',200);
	if (!event.ctrlKey && !event.shiftKey && !event.metaKey) //if ctrl down 
	{
		$('.file_on_select').removeClass('file_on_select');
		$(this).addClass('file_on_select');
	}
	else
	{
		$(this).toggleClass('file_on_select');
	}
}

function file_on_over(event)
{
	$(this).addClass('file_on_over');
}

function file_on_out(event)
{
	$(this).removeClass('file_on_over');
}

function image_preview(event)
{
	if (!event) event = window.event;
	if (window.rename_timer) clearTimeout(window.rename_timer);
	event.returnValue = false;
	debug('preview image:'+$(this).attr('path'));
	preview($(this).attr('path'));
	return false;
}

function str_replace(search, replace, str)
{
	var regex = new RegExp(search, "g");
	return str.replace(regex, replace);
}

function getstrlength(sChars)
{
	if (!sChars) return 0;
	else return sChars.replace(/[^\x00-\xff]/g,"xx").length;
}

function getlengthstr(sSource, iLen)
{
	if(getstrlength(sSource) <= iLen) return sSource;
	var ELIDED = "...";
	
	var str = "";
	var l = 0;
	var schar;
	for(var i=0; schar=sSource.charAt(i); i++)
	{
		str += schar;
		l += (schar.match(/[^\x00-\xff]/) != null ? 2 : 1);
		if(l >= iLen - ELIDED.length) break;
	}
	str += ELIDED;
	return str;
}

function dealpath(s)
{
	if (!s) return "";
	if (window.searching)
	{
		p = decode_path(window.search_path.replace(window.root,''));
		p = window.customer_name+'/'+p;
		return p + '　"'+window.search_keyword + '"的搜索结果';
		//return 'Search result of "'+window.search_keyword + '" in "'+ p +'"' ;
	}
	if (s.indexOf(root) != 0) opendir(root);
	s = s.replace(root,'');
	var arr=s.split("/"),s1 = root;
	var r = "<a href='javascript:opendir(\""+root+"\");' folder='yes' name='{ROOT}' path='"+root+"' >{ROOT}</a>/";
	
	for(var i=0;i<arr.length;i++)
	{
		if (!arr[i]) continue;
		s1=s1+arr[i]+"/";
		r=r+"<a href='javascript:opendir(\""+s1+"\");' folder='yes' name='"+arr[i]+"' path='"+s1+"'>"+getlengthstr(arr[i],20)+"</a>/";
	}
	return r;
} 

function dealpath4copy(s)
{
	if (!s) return "";
	if (s.indexOf(root) != 0) opendir(root);
	s = s.replace(root,'');
	var arr=s.split("/"),s1 = root;

	r = window.customer_name+'/';
	
	for(var i=0;i<arr.length;i++)
	{
		if (!arr[i]) continue;
		s1=s1+arr[i]+"/";
		r=r+getlengthstr(name_decode(arr[i]),20) + "/";
	}
	return r;
} 

var filei=0;
function addupfile()
{
	filei++;
	var span = $_("updivdata");
	var divObj = document.createElement("div");
	
	divObj.id = "upfileinput"+filei;
	divObj.innerHTML = "{LOCAL_FILE}: <INPUT name='myfile"+filei+"' TYPE='file'  onchange='check_upload_file(this)'  size='70' /> <!--input type=button class=bt onclick='delupfile("+filei+")' value='{LANG_DELETE}' /-->";
	span.appendChild(divObj);
}

function delupfile(i) 
{
    var span = document.getElementById("updivdata");
    var divObj = document.getElementById("upfileinput"+i);
    if (span != null && divObj != null) 
    {
        span.removeChild(divObj);
    }
	if (span.childNodes.length == 0)
	{
		addupfile();
	}
}

function clearupfile()
{
	$('#updivdata').html('');
	addupfile();
}

function checkfilename(f)
{
	if (f.match(/^\.+/))
	{
		alert('{ILLEGAL_NAME}');
		return;
	}
	//var limit=Array('\\','\/',':','*','?','"','<','>','|','\'');
	var limit=Array('\\','\/',':','*','?','"','<','>','|');
	for(var i=0;limit[i];i++)
		if (f.indexOf(limit[i]) != -1)
		{
			window.movenotice = 1;
			notice("{ILLEGAL_NAME}:\n"+"\\ \/ : * ? \" < > |");
			return false;
		}
	return true;
}

function close_notice(delay)
{
	if (!delay) window.movenotice = 1;
	$('#notice').fadeOut(500,function(){ window.movenotice = 1; });
}

function close_ctrl()
{
	$_('ctrl').style.display = "none";
}

function notice(s,t,x,y,is_html)
{
	$('#notice').stop().fadeTo(10,1);
	if (window.notice_timer) clearTimeout(window.notice_timer);
	var t = t?t:3;
	if ($_('notice'))
	{
		d = $_('notice');
	}
	else
	{
		var d = document.createElement("div");
		d.id = "notice";
		d.style.display = 'none';
		document.body.appendChild(d);
	}

	if ($.browser.msie && !is_html)
	{
		d.innerText = s;
	}
	else if (!$.browser.msie && !is_html)
	{
		d.innerHTML = "<pre style='font-size:12px'>"+s+"</pre>";
	}
	else
	{
		d.innerHTML = s;
	}
	
	with(d.style)
	{
		zIndex = 32329;
		top = y?y:window.mouse_y;
		left = x?x:window.mouse_x+20;
	}
	$(d).fadeIn(300);
	
	d.onmouseover = function()
	{
		if (window.notice_timer) clearTimeout(window.notice_timer);
	}
	d.onmouseout = function ()
	{
		window.notice_timer = setTimeout("$('#notice').fadeOut(500);window.movenotice=1;",t*1000);
	}
	window.notice_timer = setTimeout("$('#notice').fadeOut(500);window.movenotice=1;",t*1000);
	return;
}

function get_page_size()
{
	var div = document.createElement('div');
	$(div).css(
	{
		position:'absolute',
		top:0,left:0,
		margin:0,border:0,padding:0,
		width:'100%',height:'100%',
		zIndex:99,
		backgroundColor:'transparent'
	}).html(' ');
	$(document.body).append(div);
	var re = {};
	re.height = ($(document).height() > $(div).height())?$(document).height():$(div).height();
	re.width = ($(document).width() > $(div).width())?$(document).width():$(div).width();
	document.body.removeChild(div);
	return re;
}

function getcookie(name)
{
	var cookie = document.cookie.toString();
	if (cookie.indexOf(name) == -1) return false;
	var arr = cookie.split(name);
	cookie = arr[1];
	arr = cookie.split(';');
	cookie = arr['0'];
	cookie = cookie.replace('=','');
	return cookie;
}

function check_clipboard()
{
	if (getcookie('action1') == 'cut' || getcookie('action1') == 'copy')
	{
		if (getcookie('sdir') || getcookie('sfile')) return true;
	}
	return false;
}

function name_decode(s)
{
	s = s.replace(',','+').replace('_','/');
	var re = base64_decode(s);
	return re;
}

function decode_path(s)
{
	if (!s) return '';
	var arr = s.split('/');
	var re = '';
	for(var i =0;i<arr.length;i++)
	{
		re += name_decode(arr[i])+'/';
	}
	re = re.substring(0,re.length-1);
	return re;
}

function utf16to8(str) 
{
    var out, i, len, c;

    out = "";
    len = str.length;
    for(i = 0; i < len; i++) 
	{
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) 
		{
            out += str.charAt(i);
        } 
		else if (c > 0x07FF) 
		{
            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
            out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));
            out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
        } 
		else 
		{
            out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));
            out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
        }
    }
    return out;
}

function utf8to16(str) 
{
    var out, i, len, c;
    var char2, char3;

    out = "";
    len = str.length;
    i = 0;
    while(i < len) 
	{
        c = str.charCodeAt(i++);
        switch(c >> 4)
        {
          case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:

            out += str.charAt(i-1);
            break;
          case 12: case 13:

            char2 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
            break;
          case 14:

            char2 = str.charCodeAt(i++);
            char3 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x0F) << 12) |
                                           ((char2 & 0x3F) << 6) |
                                           ((char3 & 0x3F) << 0));
            break;
        }
    }

    return out;
}

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);

function base64encode(str) 
{
    var out, i, len;
    var c1, c2, c3;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if(i == len)
        {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt((c1 & 0x3) << 4);
            out += "==";
            break;
        }
        c2 = str.charCodeAt(i++);
        if(i == len)
        {
            out += base64EncodeChars.charAt(c1 >> 2);
            out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
            out += base64EncodeChars.charAt((c2 & 0xF) << 2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
        out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}

function base64decode(str) 
{
    var c1, c2, c3, c4;
    var i, len, out;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) 
	{
        do {
            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while(i < len && c1 == -1);
        if(c1 == -1)
            break;

        do {
            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while(i < len && c2 == -1);
        if(c2 == -1)
            break;

        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

        do {
            c3 = str.charCodeAt(i++) & 0xff;
            if(c3 == 61)
                return out;
            c3 = base64DecodeChars[c3];
        } while(i < len && c3 == -1);
        if(c3 == -1)
            break;

        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

        do {
            c4 = str.charCodeAt(i++) & 0xff;
            if(c4 == 61)
                return out;
            c4 = base64DecodeChars[c4];
        } while(i < len && c4 == -1);
        if(c4 == -1)
            break;
        out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}

function base64_decode(str)
{
        return utf8to16(base64decode(str));
}
